package com.zelma.agent.service.impl;


import com.zelma.agent.dao.UsergroupbuyDao;
import com.zelma.agent.entity.GroupbuyEntity;
import com.zelma.agent.entity.UsergroupbuyEntity;
import com.zelma.agent.service.GroupbuyService;
import com.zelma.agent.service.UsergroupbuyService;
import com.zelma.agent.util.IdWorker;
import com.zelma.common.utils.PageUtils;
import com.zelma.common.utils.Query;
import com.zelma.common.utils.R;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

@Service("usergroupbuyService")
public class UsergroupbuyServiceImpl extends ServiceImpl<UsergroupbuyDao, UsergroupbuyEntity> implements UsergroupbuyService {

    @Autowired
    private GroupbuyService groupbuyService;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private RedissonClient redissonClient;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<UsergroupbuyEntity> page = this.page(
                new Query<UsergroupbuyEntity>().getPage(params),
                new QueryWrapper<UsergroupbuyEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public R visit(String groupBuyId) {



        //死锁,lua脚本，保证原子性，2S
        //watch dog()

        //尝试获取锁
        Boolean lock = stringRedisTemplate.opsForValue().setIfAbsent("lock_groupBuyId"+groupBuyId,"11");

        if(lock){
            try {
                //用户编号
                String uid=String.valueOf(idWorker.nextId());
                //根据团购编号查询团购信息
                GroupbuyEntity groupbuyEntity = groupbuyService.getById(groupBuyId);
                if(groupbuyEntity==null){
                    return R.error("团购编号有误");
                }
                //幂等处理 防止用户重复报名
                UsergroupbuyEntity ugb= baseMapper.getByUidGid(uid,groupBuyId);
                if(ugb!=null){
                    return R.error("不能重复报名");
                }
                long now = new Date().getTime();
                if(now<groupbuyEntity.getGroupbuyStartdate().getTime()){
                    return R.error("团购还未开始");
                }
                if(now>groupbuyEntity.getGroupbuyEnddate().getTime()){
                    return R.error("团购已经结束");
                }
                if(groupbuyEntity.getGroupbuyWhetherStatus()==0){
                    return R.error("还未开团，请等待");
                }
                //查询团购报名人数
                int count=baseMapper.getVisitCountByGbid(groupBuyId);
                if(groupbuyEntity.getGroupbuyNum()<=count){
                    return R.error("报名人数已满");
                }
                //可以报名、添加用户团购中间表
                UsergroupbuyEntity usergroupbuyEntity = new UsergroupbuyEntity();
                usergroupbuyEntity.setId(String.valueOf(idWorker.nextId()));
                usergroupbuyEntity.setGid(groupBuyId);
                usergroupbuyEntity.setUid(uid);
                usergroupbuyEntity.setStatus(0);
                usergroupbuyEntity.setLogicdel(0);
                baseMapper.insert(usergroupbuyEntity);
                return R.ok();
            }catch (Exception e){
                return null;
            }finally {
                //删除锁
                //保证对比删除是原子性的
                // get和delete原子操作 lua脚本
                String script = "if redis.call(\"get\",KEYS[1]) == ARGV[1] then\n" +
                        "    return redis.call(\"del\",KEYS[1])\n" +
                        "else\n" +
                        "    return 0\n" +
                        "end";
                stringRedisTemplate.execute(new DefaultRedisScript<Long>(script, Long.class),
                        Arrays.asList("lock_groupBuyId"+groupBuyId),"11");

            }
        }else {
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return visit(groupBuyId);
        }
    }



}